package se392.ateam2006.user;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.ejb.CreateException;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import javax.persistence.Query;

import se392.ateam2006.authentication.GroupEntity;
import se392.ateam2006.authentication.GroupMgmtLocal;
import se392.ateam2006.authentication.GroupMgmtRemote;
import se392.ateam2006.meetingmgmt.MeetingMgmtBean;
import se392.ateam2006.meetingmgmt.MeetingMgmtLocal;
import se392.ateam2006.meetingmgmt.MeetingMgmtRemote;
import se392.ateam2006.meetingmgmt.meeting.MeetingEntity;
import se392.ateam2006.resourcemgmt.ResourceMgmtBean;
import se392.ateam2006.resourcemgmt.ResourceMgmtLocal;
import se392.ateam2006.resourcemgmt.ResourceMgmtRemote;
import se392.ateam2006.resourcemgmt.participant.ParticipationEntity;
import se392.ateam2006.resourcemgmt.participant.exclusionset.ExclusionRangeEntity;

/**
 * Stateless EJB that handles all operations delaing with users - creating and deleting, etc
 * @author Ateam (Matthew Bennett, Claire Melton, Shingai Manyiwa, John Adderley)
 * @version 25/03/07
 */
@Stateless
public class UserMgmtBean implements UserMgmtRemote, UserMgmtLocal, Serializable {
    
    @PersistenceContext
    private EntityManager em;
    
    @EJB
    private ResourceMgmtLocal resources;
    @EJB
    private MeetingMgmtLocal meetings;
    @EJB
    private GroupMgmtRemote groups;
    
    /**
     * Default constructor required as this is an EJB
     */
    public UserMgmtBean() { }
    
    /**
     * Create and persist a new user
     * @param email - String, the email address of the user
     * @return UserEntity - the newly persisted user
     */
    public UserEntity createUser(String email) {
        UserEntity user = getUserByID(email);
        if(user == null) {
            user = new UserEntity(email);
            em.persist(user);
        }
        return user;
    }
    
    /**
     * Create and persist a new user
     * @param email - String, the email address of the user
     * @param firstname - String, the first name of the user
     * @param lastname - String, the last name of the user
     * @return UserEntity - the newly persisted user
     */
    public UserEntity createUser(String email, String firstname, String lastname) {
        UserEntity user = getUserByID(email);
        if(user == null) {
            user = new UserEntity(email, firstname, lastname);
            em.persist(user);
        } else {
            user.setForename(firstname);
            user.setSurname(lastname);
        }
        return user;
    }
    
    public void createUser(UserEntity user){
        UserEntity userEnt = getUserByID(user.getEmail());
        if(userEnt == null) {
            em.persist(user);
        }
    }
        
    /**
     * Find a user based on their ID
     * @param userId - String, the ID of the user to find
     * @return UserEntity - the found user (or null if not found)
     */
    public UserEntity getUserByID(String userId) {
        return (UserEntity) em.find(UserEntity.class, userId);
    }

    /**
     * Get the number of users in the database
     * @return int - the number of users
     */
    public int getUserCount() {
        Query q = em.createQuery("SELECT u FROM UserEntity u");
        return q.getResultList().size();
    }
    
    /**
     * Remove all users from the database
     */
    public void removeAllUsers() {
        Collection<UserEntity> users = getAllUsers();
        for(UserEntity u : users) {
            deleteUser(u);
        }
    }
    
    /**
     * Get all users in the database
     * @return Collection - all of the users in the database
     */
    public Collection getAllUsers() {
        Query q = em.createQuery("Select u from UserEntity u");
        return q.getResultList();
    }

    /**
     * Delete a user form the database
     * @param u - UserEntity, the user to remove
     */
    public void deleteUser(UserEntity u) {
        em.flush();
        Query q = null;
        String id = u.getEmail();
        Collection<ParticipationEntity> parts = resources.findParticipationsByUser(u);
        
        for(ParticipationEntity p : parts) {
            resources.removeParticipation(p);
        }
        
        Collection<ExclusionRangeEntity> excs = resources.getExclusionSetsForParticipant(u);
        
        for(ExclusionRangeEntity p : excs) {
            resources.deleteExclusionRange(p);
        }
        
        
        Collection<MeetingEntity> meets = meetings.findMeetingsByInitiator(u);
        
        for(MeetingEntity p : meets) {
            meetings.deleteMeeting(p);
        }        
        
        try{
            em.remove(em.find(UserEntity.class, id));
        } catch(Exception e) {
            e.printStackTrace();
        }
        
        q = em.createQuery("DELETE FROM MeetingEntity p WHERE p.id = '" + id + "'");
        q.executeUpdate();
    
    } 
    
    /*
     * Method used to set the booking permissions for a selected user, specifying
     * which rooms they are allowed to use when creating a meeting
     * 
     * @param email the users email address so they can be found
     * @param permission the users specified permissions
     */
    public boolean setBookingPermissions(String email, String permissions) throws Exception {
        UserEntity user = getUserByID(email);
        try {
            GroupEntity group = groups.getGroupById(permissions);
            if(group != null) {
                user.addPermission(group);
                em.merge(user);
                return true;
            }
            return false;
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
}
